/**
 * Copyright (c) 2013 Axa Holding Belgium, SA. All rights reserved.
 * This software is the confidential and proprietary information of the AXA Group.
 */
package chabernac.gravidroid.paint;

import java.util.HashMap;
import java.util.Map;

import android.graphics.Color;
import chabernac.android.draw.AbstractDrawable;
import chabernac.android.draw.DrawableComposite;
import chabernac.gravidroid.model.GravitySimulator;
import chabernac.gravidroid.model.LineForce;
import chabernac.gravidroid.model.LinearMass;
import chabernac.gravidroid.model.Mass;
import chabernac.gravidroid.model.Structure;
import chabernac.gravidroid.model.StructurePredicate;
import chabernac.gravidroid.model.iMass;
import chabernac.util.Iterables;

public class DrawableFactory {
	private boolean isDebug = false;
	private boolean isDrawIntersection = true;
	private boolean isDrawForces = true;
	private boolean isDrawInternals = true;
	private boolean isDrawCenter = true;

	private final GravitySimulator myGravitySimulator;

	private int myLastNumberOfDrawables = -1;
	private DrawableComposite myDrawable = new DrawableComposite();

	private final Map<Object, AbstractDrawable> myDrawableCache = new HashMap<Object, AbstractDrawable>();

	public DrawableFactory(GravitySimulator aGravitySimulator) {
		super();
		myGravitySimulator = aGravitySimulator;
	}

	public AbstractDrawable createDrawable() {
		if (isDebug || myLastNumberOfDrawables != myGravitySimulator.getMasses().size() || myDrawable == null) {
			myDrawable.clear();

			for (iMass theMass : myGravitySimulator.getMasses()) {
				myDrawable.addDrawable(getDrawableForMass(theMass));
			}

			if (isDebug) {
				for (Mass theMass : myGravitySimulator.getInternalMasses()) {
					// draw intersecting linear mass
					if (isDrawIntersection && theMass.intersectionLinearMass != null) {
						for (LinearMass theLMass : theMass.intersectionLinearMass) {
							myDrawable.addDrawable(new LinearMassDrawable(theLMass, Color.YELLOW, 20).setLayer(-100));
						}
					}

					if (isDrawForces) {
						myDrawable.addDrawable(new ForceDrawable(theMass));
					}
				}

				Iterable<iMass> theStructures = Iterables.filter(myGravitySimulator.getMasses(), new StructurePredicate());
				if (isDrawInternals) {
					for (iMass theStructure : theStructures) {
						for (LinearMass theInteralLMass : ((Structure) theStructure).getInternalLinearMasses()) {
							myDrawable.addDrawable(new LinearMassDrawable(theInteralLMass, Color.YELLOW, 2));
						}
					}
				}

				if (isDrawCenter) {
					for (iMass theMass : myGravitySimulator.getMasses()) {
						myDrawable.addDrawable(new CenterDrawable(theMass));
					}
				}
			}

			// theComposite.addDrawable(new BorderDrawable());
			myDrawable.sort();
			myLastNumberOfDrawables = myGravitySimulator.getMasses().size();
		}
		return myDrawable;
	}

	private AbstractDrawable getDrawableForMass(iMass aMass) {
		if (!myDrawableCache.containsKey(aMass)) {
			if (aMass instanceof Mass) {
				myDrawableCache.put(aMass, new MassDrawable((Mass) aMass));
			} else if (aMass instanceof LinearMass) {
				// LinearMass theLinearMass = (LinearMass)aMass;
				// DrawableComposite theComposite = new DrawableComposite();
				// theComposite.addDrawable(new MassDrawable(theLinearMass.getMass1()));
				// theComposite.addDrawable(new MassDrawable(theLinearMass.getMass2()));
				myDrawableCache.put(aMass, new LinearMassDrawable((LinearMass) aMass));
				// myDrawableCache.put(aMass, theComposite);

			} else if (aMass instanceof LineForce) {
				myDrawableCache.put(aMass, new LineForceDrawable((LineForce) aMass));
			} else if (aMass instanceof Structure) {
				myDrawableCache.put(aMass, new StructureDrawable((Structure) aMass));
			}
		}
		return myDrawableCache.get(aMass);
	}

}
